package br.uece.laconi.tac.strategy;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FilenameFilter;
import java.io.FilterInputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.zip.GZIPInputStream;

import se.sics.tac.aw.Bid;
import se.sics.tac.aw.Quote;
import se.sics.tac.aw.TACAgent;
import se.sics.tac.aw.Transaction;

public class EntertainmentKnowledge {
	public static int AW = 0;
	public static int AP = 1;
	public static int MU = 2;
	
	private float transactsRate;
	private float transactsBuyRate;
	private float transactsSellRate;
	private float numBuyTransacts;
	private float numSellTransacts;
	private float numTotalTransacts;
	public static final int SELL = 0;
	public static final int BUY = 1;
	public static final int AVERSE = 0;
	public static final int SEEKING = 1;
	private float [][] lastTransacts = new float [2][28];
	private float [] lastBids = new float [28];
	private float [] lastAsks = new float [28];
	private int logIdFixer;
	private Map<String, List<Float>> prices;
	private Map<String, List<Float>> pricesAsksQuotes;
	private Map<String, List<Float>> pricesBidsQuotes;
	private Map<String, List<Float>> asks;
	private Map<String, List<Float>> bids;
	private ArrayList<Quote> lastUpdatedQuotes;
	private int[][] clientPreferences;
	
	public EntertainmentKnowledge() {
		lastUpdatedQuotes = new ArrayList<Quote>();
		prices = new HashMap<String, List<Float>>();
		for (int i = TACAgent.MIN_ENTERTAINMENT; i <= TACAgent.MAX_ENTERTAINMENT; i++) {
			String key = TACAgent.getAuctionTypeAsString(i);			
			List<Float> value = new ArrayList<Float>();
			prices.put(key, value);	
		}
		pricesAsksQuotes = new HashMap<String, List<Float>>();
		for (int i = TACAgent.MIN_ENTERTAINMENT; i <= TACAgent.MAX_ENTERTAINMENT; i++) {
			String key = TACAgent.getAuctionTypeAsString(i);			
			List<Float> value = new ArrayList<Float>();
			pricesAsksQuotes.put(key, value);	
		}
		pricesBidsQuotes = new HashMap<String, List<Float>>();
		for (int i = TACAgent.MIN_ENTERTAINMENT; i <= TACAgent.MAX_ENTERTAINMENT; i++) {
			String key = TACAgent.getAuctionTypeAsString(i);			
			List<Float> value = new ArrayList<Float>();
			pricesBidsQuotes.put(key, value);	
		}
		asks = new HashMap<String, List<Float>>();
		for (int i = TACAgent.MIN_ENTERTAINMENT; i <= TACAgent.MAX_ENTERTAINMENT; i++) {
			String key = TACAgent.getAuctionTypeAsString(i);			
			List<Float> value = new ArrayList<Float>();
			asks.put(key, value);	
		}
		bids = new HashMap<String, List<Float>>();
		for (int i = TACAgent.MIN_ENTERTAINMENT; i <= TACAgent.MAX_ENTERTAINMENT; i++) {
			String key = TACAgent.getAuctionTypeAsString(i);			
			List<Float> value = new ArrayList<Float>();
			bids.put(key, value);	
		}
	}
	
	public void setClientPreferences(int client, int awBonus, int apBonus, int muBonus) {
		clientPreferences[client][AW] = awBonus;
		clientPreferences[client][AP] = apBonus;
		clientPreferences[client][MU] = muBonus;
	}
	
	public float getReferencePrice(int auction) {		
		return getReferencePrice(TACAgent.getAuctionTypeAsString(auction));
	}
	
	public float getReferencePrice(String auctionType) {		
		return prices.get(auctionType).get(prices.get(auctionType).size()/2);
	}
	
	public void load(String folderName) {
		try
		{
			resetTransactsRate();
			
			String line = null;
			File folder = null;
			FilenameFilter logFilter = null;
			FileInputStream input = null;
			FilterInputStream stream = null;
			BufferedReader reader = null;
			
			folder = new File(folderName);

			if (folder.exists() == false ||	folder.isDirectory() == false) {
				return;
			}
			
			logFilter = new FilenameFilter() { 
				public boolean accept(File b, String name) { 
					return name.endsWith(".log.gz"); 
				} 
			};

			for (File file : folder.listFiles(logFilter)) {
				input = new FileInputStream(file);
				stream = new GZIPInputStream(input);
				reader = new BufferedReader(new InputStreamReader(stream));

				while ((line = reader.readLine()) != null) {
					parse(line, prices);
				}

				reader.close();
				stream.close();
				input.close();
			}
			
//*********************************** DEBUG ************************************************//
//			for (String key : prices.keySet()) {											//
//				System.out.println(key + ":" + prices.get(key));							//
//			}																				//
//******************************************************************************************//
		}
		catch (Exception e) {
			System.out.println(e.getMessage());
		}
	}
	
	private void parse(String linelog, Map<String, List<Float>> prices) {
		String[] content = linelog.split(",");		
		if (content[1].equals("u")) {
			if (content[3].equals("0") && content[4].equals("1")) {
				logIdFixer = Integer.parseInt(content[2]);
			}
		} else if (content[1].equals("t")) {
			int auction = Integer.parseInt(content[4]) - logIdFixer;	
			if (TACAgent.getAuctionCategory(auction) == TACAgent.CAT_ENTERTAINMENT) {
				String auctionType = TACAgent.getAuctionTypeAsString(auction);
				Float price = Float.parseFloat(content[6]);
				if( price != 0 ) {
					prices.get(auctionType).add(price);
					Collections.sort(prices.get(auctionType));
				}	
			}
		} 
	}

	public void update(Bid bid) {	}
	
	public void update(Quote quote) {
		int auction = quote.getAuction();
		if (TACAgent.getAuctionCategory(auction) == TACAgent.CAT_ENTERTAINMENT) {
			for (Quote old : lastUpdatedQuotes) {
				if (old.getAuction() == auction) {
					lastUpdatedQuotes.remove(old);
					break;
				}
			}
			lastUpdatedQuotes.add(quote);
			updateTransactsRate(quote);
		}
	}

	public void update (Transaction transaction) {
		int auction = transaction.getAuction();
		float price = transaction.getPrice();
		if (TACAgent.getAuctionCategory(auction) == TACAgent.CAT_ENTERTAINMENT) {
			String auctionType = TACAgent.getAuctionTypeAsString(auction);
			prices.get(auctionType).add(price);
			Collections.sort(prices.get(auctionType));
			//atualiza taxa de transacoes do agente
			updateAgentTransacts(transaction);
		}
	}
	
	public ArrayList<Quote> getLastUpdatedQuotes() {
		ArrayList<Quote> quotes = lastUpdatedQuotes;
		lastUpdatedQuotes = new ArrayList<Quote>();
		return quotes;
	}
	
	public int[][] clientPreference = new int[8][3];
	
	public void updateLastBids(int auction, float price){
		//this.lastBids[auction] = price;
		String auctionType = TACAgent.getAuctionTypeAsString(auction);
		List<Float> bidsList = this.bids.get(auctionType);
		bidsList.add(price);
	}	
	
	public void updateLastAsks(int auction, float price){
		//this.lastAsks[auction] = price;
		String auctionType = TACAgent.getAuctionTypeAsString(auction);
		List<Float> asksList = this.asks.get(auctionType);
		asksList.add(price);
	}		
	
	public float getTransactsBuyRate(){
		return this.transactsBuyRate;
	}
	public float getTransactsSellRate(){
		return this.transactsSellRate;
	}
	
	//atualiza a taxa de transacoes do agente
	private void updateAgentTransacts(Transaction transaction){
		int auction = transaction.getAuction();
		float price = transaction.getPrice();
		float quantity = (float)Math.abs(transaction.getQuantity());
//		if(lastBids[auction] == price){
//			this.numBuyTransacts += quantity;
//			this.transactsBuyRate = this.numBuyTransacts / this.numTotalTransacts;
//		}else if (this.lastAsks[auction] == price){
//			this.numSellTransacts += quantity;		
//			this.transactsSellRate = this.numSellTransacts / this.numTotalTransacts;
//		}
		String auctionType = TACAgent.getAuctionTypeAsString(auction);
		List<Float> bidsList = this.bids.get(auctionType);
		for (float bidPrice : bidsList) {
			if(bidPrice == price){
				this.numBuyTransacts += quantity;
				this.transactsBuyRate = this.numBuyTransacts / this.numTotalTransacts;
				System.out.println("######### TRANS DE COMPRA REALIZADA - LEILAO " + auction + " VALOR: " + price);
			}
		}
		List<Float> asksList = this.asks.get(auctionType);
		for (float askPrice : asksList) {
			if(askPrice == price){
				this.numSellTransacts += quantity;		
				this.transactsSellRate = this.numSellTransacts / this.numTotalTransacts;
				System.out.println("######### TRANS DE VENDA REALIZADA - LEILAO " + auction + " VALOR: " + price);
			}
		}
	}
	
	//atualiza a taxa total de transacoes 	
	private void updateTransactsRate(Quote quote){
		int auction = quote.getAuction();
		String auctionType = TACAgent.getAuctionTypeAsString(auction);
		List<Float> asks = pricesAsksQuotes.get(auctionType);
		asks.add(quote.getAskPrice());
		List<Float> bids = pricesBidsQuotes.get(auctionType);
		bids.add(quote.getAskPrice());
		System.out.println("TRANSACAO no leilao "+ auction);
		int asksSize = asks.size(); 
		if(asksSize > 1)
			if(asks.get(asksSize - 2).floatValue() < asks.get(asksSize - 1).floatValue()){
				this.numTotalTransacts += 1.0f;
				System.out.println("VENDA preco anterior " + asks.get(asksSize - 2) + " preco atual " + asks.get(asksSize - 1));
			}
//		int bidsSize = bids.size();
//		if(bidsSize > 1)
//			if(bids.get(bidsSize - 2).floatValue() > bids.get(bidsSize - 1).floatValue()){
//				this.numTotalTransacts += 1.0f;
//				System.out.println("COMPRA preco anterior " + bids.get(bidsSize - 2) + " preco atual " + bids.get(bidsSize - 1));
//			}
//		visualizarEstatisticaTransacoes();
	}
	
	public void resetTransactsRate(){
		this.numSellTransacts = 0.0f;
		this.numBuyTransacts = 0.0f;
		this.transactsBuyRate = 0.0f;
		this.transactsSellRate = 0.0f;
		this.numTotalTransacts = 0.0f;
		this.lastBids = null; 
		this.lastBids = new float [28]; 
		this.lastAsks = null; 
		this.lastAsks = new float [28];		
	}
	
	public void visualizarEstatisticaTransacoes(){
		System.out.println("numAgentSellTransacts "+this.numSellTransacts);
		System.out.println("numAgentBuyTransacts "+this.numBuyTransacts);
		System.out.println("numTotalTransacts "+this.numTotalTransacts);
		System.out.println("transactsBuyRate "+this.transactsBuyRate);
		System.out.println("transactsSellRate "+this.transactsSellRate);
	}

	public static void visualizarLastTransacts(float [][] matriz){
//		StringBuffer linha = new StringBuffer();
//		StringBuffer coluna = new StringBuffer();
//		
//		linha.append("\tleilao 1\t2\t3\t4\t5 ... \t28\n");
//
//		for (int i = 0; i < matriz.length; i++) {
//			for (int j = 0; j < matriz[i].length; j++) {
//				coluna.append(matriz[i][j]+"\t");
//			}
//			String tipo = (i == BUY ? "COMPRA": "VENDA");
//			linha.append(tipo+" "+coluna.toString()+"\n");
//			coluna.delete(0, coluna.length());
//		}
//		System.out.println(linha.toString());
	}
}
